package data.vectors.implementation;

import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import data.vectors.*;



/**
 * This class implements a sparse vector in memory
 * @author denoyer
 *
 */
public class DoubleVector_Sparse_Memory extends DoubleVectorWritable {

	/**
	 * The hash map (feature,value)
	 */
	protected AbstractMap<Integer,Double> map;

	/**
	 * The size of the vector
	 */
	protected int size;

	public DoubleVector_Sparse_Memory()
	{
		this.size=-1;
		map=new HashMap<Integer,Double>();
	}
	
	public DoubleVector_Sparse_Memory(int size)
	{
		this.size=size;
		map=new HashMap<Integer,Double>();
	}

	/**
	 * Create a new memory vector from a vector
	 * @param v
	 */
	public DoubleVector_Sparse_Memory(DoubleVector v)
	{
		this.size=v.size();
		map=new HashMap<Integer,Double>();
		DoubleVectorIterator it=v.getNonNullIterator();
		int nb=0;
		while(it.hasNext())
		{
			it.next();	
			if (it.getCurrentValue()!=0.0)
				setValue(it.getCurrentFeature(),it.getCurrentValue());
			nb++;
		}
	}
	
	
	
	public final  double getValue(int i) {
		Integer key=new Integer(i);
		if (map.containsKey(key))
			return(map.get(key).doubleValue());
		return(0.0);
	}

	
	public int size() {
		return size;
	}

	
	public void setValue(int feature, double value) {
		if (value==0)
		{
			if (map.containsKey(feature)) map.remove(feature);
		}
		else
			map.put(feature,new Double(value));		
		if(feature+1>size)
			size=feature+1;// prise en compte du zero
	}


	/**
	 * P�rmet de recopier un autre vecteur en demarrant � la dimension specifiee
	 */
	public void copy(DoubleVector v,int position)
	{
		DoubleVectorIterator iterator=v.getNonNullIterator();
		while(iterator.hasNext())
		{
			iterator.next();
			int nf=iterator.getCurrentFeature()+position;
			setValue(nf, iterator.getCurrentValue());
		}
	}
	
	//========================================== CONNECTIONS ==========================================
	
	public DoubleVectorIterator getIterator() {
		return(new BasicDoubleVectorIterator(this));
	}

	
	public final DoubleVectorIterator getNonNullIterator() {
		return(new SparseDoubleVectorIterator(map));		
	}

	
	public int getNumberNonNullValues() {
		return map.size();
	}


	
	protected final  class SparseDoubleVectorIterator implements DoubleVectorIterator {

		private Iterator<Map.Entry<Integer,Double>> iterator;
		Map.Entry<Integer,Double> current_value;
		
		public SparseDoubleVectorIterator(AbstractMap<Integer,Double> map)
		{
			this.iterator=map.entrySet().iterator();	
		}
		
		public final int getCurrentFeature() {
			return(current_value.getKey());
		}

		public final double getCurrentValue() {
			return(current_value.getValue());
		}

		public final boolean hasNext() {
			return this.iterator.hasNext();
		}

		public final void next() {
			current_value=iterator.next();
		}

	}


}
